import { Style, Fill, Stroke, Circle, Text, Icon } from "ol/style";
import { Tile as TileLayer, Vector as VectorLayer } from "ol/layer";
import { XYZ, Vector as VectorSource } from "ol/source";
import { Map, View, Feature } from "ol";
import { FullScreen } from "ol/control";
import { getCenter } from 'ol/extent';
import GeoJSON from "ol/format/GeoJSON";
import { uploadJsonAsFile } from '@/utils/axios';
import { Polygon, MultiPolygon, Point } from 'ol/geom';
import * as turf from "@turf/turf";

import Draw, { createBox } from 'ol/interaction/Draw'

const originLayers = [
  {
    visible: true,
    urlPattern: "https://wprd0{1-4}.is.autonavi.com/appmaptile?lang=zh_cn&size=1&style=7&x={x}&y={y}&z={z}"
  },
  {
    visible: false,
    urlPattern: "https://wprd0{1-4}.is.autonavi.com/appmaptile?lang=zh_cn&size=1&style=6&x={x}&y={y}&z={z}"
  },
  {
    visible: false,
    urlPattern: 'https://gx.jdfktech.com:18279/yjearth4.0/data/mbt/d2a3af49472423af91e5999f83b6e705/{z}/{x}/{y}.png'
  },
 {

  visible: false,
  urlPattern: 'https://{a-c}.tile.opentopomap.org/{z}/{x}/{y}.png'
 }

];


/**
 * 
 * @param fill  填充颜色
 * @param stroke  线颜色
 * @param image  样式
 * @returns 
 */
export function createStyle(fill: string, stroke: string, image?: string) {
  let img;
  if (image) {
    img = new Circle({  //点样式
      radius: 5,
      fill: new Fill({
        color: image
      })
    })
  }
  return new Style({
    fill: new Fill({
      color: fill
    }),
    stroke: new Stroke({
      width: 2,
      color: stroke,
    }),
    image: img,
  });
}
export function createSimpleStyle(color){
  return new Style({
    fill: new Fill({
      color: color
    }),
  });
}


export function createStyleText(fill: string, stroke: string, name?: string) {
  return new Style({
    text: new Text({
      text: name,
      offsetY: -20, // 调整文本位置
      font: '12px Calibri,sans-serif',
      fill: new Fill({
        color: fill
      }),
      stroke: new Stroke({
        color: stroke,
        width: 3
      })
    })
  });
}


export function createBaseLayers() {
  const layers: any = [];
  originLayers.forEach(l => {
    layers.push(
      new TileLayer({
        source: new XYZ({
          url: l.urlPattern
        }),
        visible: l.visible
      })
    )
  });
  return layers;
}

export function createMap(center) {
  return new Map({
    target: "map",
    controls: [new FullScreen({
      source: document.getElementById('fullscreen-container') as any
    })],
    layers: createBaseLayers(),
    view: new View({
      // 将呼市作为地图中心
      center: center,
      zoom: 8,
      projection: "EPSG:4326",
    }),
  });
}

export function mapChangeType(layers: any, x: any, active: any) {

  if (!layers) {
    return;
  }
  const layerLength = layers.values_.length;

  if (layerLength >= active.length) {
    buildActivueStatus(x, active);
    active.forEach((val: any, idx: any) => {
      const layer = layers.array_[idx]
      layer.setVisible(val);
    })
  }
}
function buildActivueStatus(index: any, active: any) {
  active.forEach((it, idx) => {
    active[idx] = false;
  });
  active[index] = true; // 设置激活的键为 true
}

export function outputJson(features) {
  const jsonObj = new GeoJSON().writeFeatures(features);
  return uploadJsonAsFile(jsonObj);
}

export function loadGeoJson(vectorId: any, map: any) {
  if (vectorId) {
    const source = new VectorSource({
      url: baseUrl(vectorId),
      format: new GeoJSON()
    });
    const geoJsonLayer = new VectorLayer({ source: source });
    if (source) {
      map.addLayer(geoJsonLayer);
    }
    return source;
  }
  return null;
}

export function baseUrl(val) {
  return `${process.env.VUE_APP_DISK}${process.env.VUE_APP_BASE_API}/resources/file/${val}`;
}


// 线拆分逻辑处理
export function polygonCut(poly: any, line: any, tolerance = 0.000001, toleranceType: any = "kilometers") {
  // 1. 条件判断
  if (poly.geometry === void 0 || poly.geometry.type !== "Polygon") {
    console.warn("传入的必须为polygon");
    // throw "传入的必须为polygon";
    return
  }
  if (
    line.geometry === void 0 ||
    line.geometry.type.toLowerCase().indexOf("linestring") === -1
  ) {
    console.warn("传入的必须为linestring");
    // throw "传入的必须为linestring";
    return
  }

  if (line.geometry.type === "LineString") {
    if (
      turf.booleanPointInPolygon(turf.point(line.geometry.coordinates[0]), poly) ||
      turf.booleanPointInPolygon(turf.point(line.geometry.coordinates[line.geometry.coordinates.length - 1]), poly)
    ) {
      // throw "起点和终点必须在多边形之外";

      console.warn("起点和终点必须在多边形之外");
      return
    }
  }
  // 2. 计算交点，并把线的点合并
  const lineIntersect = turf.lineIntersect(line, poly);
  const lineExp = turf.explode(line);
  for (let i = 0; i < lineExp.features.length - 1; i++) {
    lineIntersect.features.push(
      turf.point(lineExp.features[i].geometry.coordinates)
    );
  }
  // 3. 计算线的缓冲区
  const lineBuffer = turf.buffer(line, tolerance, {
    units: toleranceType,
  });
  // 4. 计算线缓冲和多边形的difference，返回"MultiPolygon"，所以将其拆开
  const _body: any = turf.difference(poly, lineBuffer);
  const pieces: any = [];
  if (_body.geometry.type === "Polygon") {
    pieces.push(turf.polygon(_body.geometry.coordinates));
  } else {
    _body.geometry.coordinates.forEach(function (a: any) {
      pieces.push(turf.polygon(a));
    });
  }
  // 5. 处理点数据
  // for (p in pieces) {
  for (let p = 0; p < pieces.length; p++) {
    const piece: any = pieces[p];
    for (const c in piece.geometry.coordinates[0]) {
      const coord = piece.geometry.coordinates[0][c];
      const p = turf.point(coord);
      for (const lp in lineIntersect.features) {
        const lpoint = lineIntersect.features[lp];
        if (turf.distance(lpoint, p, toleranceType) <= tolerance * 2) {
          piece.geometry.coordinates[0][c] = lpoint.geometry.coordinates;
        }
      }
    }
  }
  // 6. 过滤掉重复点
  // // for (p in pieces) {
  // for (let p=0;p<pieces.length; p++) {
  //   const coords = pieces[p].geometry.coordinates[0];
  //   pieces[p].geometry.coordinates[0] = filterDuplicatePoints(coords);
  // }
  // 7. 将属性赋予每一个polygon，并处理id
  pieces.forEach((a: any, index) => {
    a.properties = Object.assign({}, poly.properties);
    a.properties.id += `-${index}`;
  });
  return turf.featureCollection(pieces);
}


export function drawLineCut(oldCoordinates: any, oldfeature: any, lineCoord: any, geoJsonSource) {
  const polyDikuai = turf.polygon(oldCoordinates);
  polyDikuai.properties = oldfeature.values_.attributes;

  console.log("线是", lineCoord)
  const polyline = turf.lineString(lineCoord);
  console.log(4)
  const result = polygonCut(polyDikuai, polyline);
  const colors = ['red', 'green', 'blue', 'yellow', '#f40331'];
  //绘出结果 绘制出多个个多边形
  if (result && result.features && result.features.length > 0) {
    geoJsonSource.removeFeature(oldfeature);
    for (let f = 0; f < result.features.length; f++) {
      const feature: any = result.features[f];

      if (feature.geometry && feature.geometry.type && feature.geometry.type === 'Polygon') {
        console.log('继续')
      } else {
        continue;
      }
      // let polygon1 = new ol.Polygon(feature.geometry.coordinates);
      const feature1 = new Feature({
        geometry: new Polygon(feature.geometry.coordinates || []),
        attributes: feature,
      });
      feature1.setStyle(createStyle(colors[colors.length % f], '#f40331'));
      const Area = formatArea(feature.geometry.coordinates);
      feature1.set('Area', Area);
      geoJsonSource.addFeature(feature1);
    }
  }

  const features = geoJsonSource.getFeatures();
  console.log("目前数量" + features.length)
}

export function formatArea(c: any) {
  const polygon = turf.polygon(c);
  const area = turf.area(polygon);
  return area;
}

export function joinFeatures(oldFeatures: any, source: any) {
  const coord: any = [];
  oldFeatures.forEach(ft => {
    let oldCoord: any = null;
    const geometryType = ft.getGeometry().getType();
    if (geometryType === 'Polygon') {
      oldCoord = ft.getGeometry().getCoordinates()
    } else if (geometryType === 'MultiPolygon') {
      oldCoord = ft.getGeometry().getCoordinates()[0];
    }
    coord.push(oldCoord);
  })


  const feature1 = new Feature({
    geometry: new MultiPolygon(coord),
  });
  oldFeatures.forEach(ft => {
    source.removeFeature(ft);
  });
  source.addFeature(feature1);
}

export function unionFeatures(oldFeatures: any, source: any) {

  if (oldFeatures.length == 2) {
    const fistPolygon: any = getTurfPolygon(oldFeatures[0]);
    const nextPolygon: any = getTurfPolygon(oldFeatures[1]);
    const union: any = turf.union(fistPolygon, nextPolygon);
    if (!union) {
      return;
    }
    const feature1 = new Feature({
      geometry: new Polygon(union.geometry.coordinates),
    });

    source.removeFeature(oldFeatures[0]);
    source.removeFeature(oldFeatures[1]);
    source.addFeature(feature1);
  }

}

export function unionCoordinates(feature: any, source: any) {

  const coordinates = feature.getGeometry().getCoordinates();
  const geometryType = feature.getGeometry().getType();
  if (geometryType === 'Polygon') {
    if (coordinates.length >= 2) {
      const fistPolygon: any = turf.polygon([coordinates[0]]);
      let coords: any = [];
      for (let i = 1; i < coordinates.length; i++) {
        coords = coords.concat(coordinates[i]);
      }
      console.log(coords)
      const nextPolygon: any = turf.multiPolygon([[coords]]);
      const union: any = turf.union(fistPolygon, nextPolygon);
      if (!union) {
        return;
      }
      const feature1 = new Feature({
        geometry: new Polygon(union.geometry.coordinates),
      });
      source.removeFeature(feature);
      source.addFeature(feature1);
    }
  }


}

function getTurfPolygon(feature) {
  const geometryType = feature.getGeometry().getType();
  if (geometryType === 'Polygon') {
    return turf.polygon(feature.getGeometry().getCoordinates());
  } else if (geometryType === 'MultiPolygon') {
    return turf.multiPolygon(feature.getGeometry().getCoordinates());
  }
}

export function getPointFeature(point, fill, stroke) {
  return new Feature({
    geometry: new Point(point),
    style: createStyle(fill, stroke)
  });
}

export function baiduPlaceFeatures(places) {
  return places.map(place => {
    const bdLon = place.location.lng;
    const bdLat = place.location.lat;

    return new Feature({
      geometry: new Point([bdLon, bdLat]),
      name: place.name,
      style: createStyleText('red', 'green', place.name),
      address: place.address
    });
  });
}

export function gcj02ToWgs84(gcjLon, gcjLat) {

  const gcj02pos = bd09ToGcj02(gcjLon, gcjLat);
  gcjLon = gcj02pos.lng;
  gcjLat = gcj02pos.lat;
  let dLon = transformLon(gcjLon - 105.0, gcjLat - 35.0);
  let dLat = transformLat(gcjLon - 105.0, gcjLat - 35.0);

  const radLat = gcjLat / 180.0 * Math.PI;
  let magic = Math.sin(radLat);
  magic = 1 - 0.00669342162296594323 * magic * magic;
  const sqrtMagic = Math.sqrt(magic);

  dLat = (dLat * 180.0) / ((6378245.0 * (1 - 0.00669342162296594323)) / (magic * sqrtMagic) * Math.PI);
  dLon = (dLon * 180.0) / (6378245.0 / sqrtMagic * Math.cos(radLat) * Math.PI);

  const wgsLon = gcjLon - dLon;
  const wgsLat = gcjLat - dLat;

  return { lng: wgsLon, lat: wgsLat };
}

function bd09ToGcj02(bdLon, bdLat) {
  const x = bdLon - 0.0065;
  const y = bdLat - 0.006;
  const z = Math.sqrt(x * x + y * y) - 0.00002 * Math.sin(y * Math.PI);
  const theta = Math.atan2(y, x) - 0.000003 * Math.cos(x * Math.PI);
  const gcjLon = z * Math.cos(theta);
  const gcjLat = z * Math.sin(theta);
  return { lng: gcjLon, lat: gcjLat };
}

function transformLon(x, y) {
  let ret = 300.0 + x + 2.0 * y + 0.1 * x * x + 0.1 * x * y + 0.1 * Math.sqrt(Math.abs(x));
  ret += (20.0 * Math.sin(6.0 * x * Math.PI) + 20.0 * Math.sin(2.0 * x * Math.PI)) * 2.0 / 3.0;
  ret += (20.0 * Math.sin(x * Math.PI) + 40.0 * Math.sin(x / 3.0 * Math.PI)) * 2.0 / 3.0;
  ret += (150.0 * Math.sin(x / 12.0 * Math.PI) + 300.0 * Math.sin(x / 30.0 * Math.PI)) * 2.0 / 3.0;
  return ret;
}

function transformLat(x, y) {
  let ret = -100.0 + 2.0 * x + 3.0 * y + 0.2 * y * y + 0.1 * x * y + 0.2 * Math.sqrt(Math.abs(x));
  ret += (20.0 * Math.sin(6.0 * x * Math.PI) + 20.0 * Math.sin(2.0 * x * Math.PI)) * 2.0 / 3.0;
  ret += (20.0 * Math.sin(y * Math.PI) + 40.0 * Math.sin(y / 3.0 * Math.PI)) * 2.0 / 3.0;
  ret += (150.0 * Math.sin(y / 12.0 * Math.PI) + 300.0 * Math.sin(y / 30.0 * Math.PI)) * 2.0 / 3.0;
  return ret;
}

export function createSource() {
  return new VectorSource({
    wrapX: false
  })
}

export function createLayer(soruce, style) {
  return new VectorLayer({
    source: soruce,
    style: style
  });
}

export function pointImageStyle(pngImg) {
  const styles: any = []
  styles.push(
    new Style({
      // 设置图标
      image: new Icon({
        src: require(`@/assets/image/${pngImg}.png`),
        anchor: [0.5, 0.5],
        scale: 1,
      }),
    })
  )
  return styles
}

export function getChartOptions(type: string, formatter: any) {
  // 定义全局颜色主题（可自定义）
  const colorPalette = [
    '#5470c6', '#91cc75', '#fac858', '#ee6666',
    '#73c0de', '#3ba272', '#fc8452', '#9a60b4'
  ];

  const options: any = {
    color: colorPalette, // 全局颜色，系列自动循环使用
    tooltip: {
      trigger: 'axis',
      axisPointer: { type: type },
      formatter: formatter,
    },
    grid: [],
    xAxis: [],
    yAxis: [],
    series: []
  };
  return options;
}

export function getChart(type: string, formatter: any, series: any[], axis?: any) {
  const options = getChartOptions(type, formatter);

  series.forEach(function (item, index) {
    if(!item.data){
      return;
    }
    const coloredData = item.data.map((value: number, dataIndex: number) => ({
      value: value,
      itemStyle: {
        color: options.color[dataIndex % options.color.length] // 按数据索引取色
      }
    }));
    options.grid.push({
            show: true,
            containLabel: false,
            borderWidth: 0,
            borderColor: 'green',
            width: 300,    // 加宽 grid 区域（原 70）
            height: 120,
            left: '5%',      // 左侧留白
            right: '5%',     // 右侧留白
            bottom: '15%' 
          });

    // xAxis 配置（移除 itemStyle 和 nameTextStyle 的颜色设置）
    options.xAxis.push({
      type: 'category',
      gridIndex: index,
      axisLine: { show: false },
      axisLabel: {
        interval: 0,
        rotate: 45,
        color: 'darkgreen', // 统一坐标轴标签颜色
        fontSize: 10
      },
      axisTick: { show: false },
      data: axis || item.category
    });

    // yAxis 配置保持简洁
    options.yAxis.push({
            type: 'value',
            show: true,
            min: 0.001,
            splitLine: { show: false },
            axisLabel: {
              show: false
            },
            axisLine: {
              show: false,
              onZero: false
            },
            nameGap: '1',
            axisTick: {
              show: false
            },
            nameTextStyle: {
              color: '#3c3c3c',
              fontSize: 14
            },
            gridIndex: index,
      
          });

    // 确保系列使用全局颜色（按索引自动循环）
    options.series.push({
      ...item,
      data: coloredData, // 替换为带颜色的数据
      barWidth: 30,  // 柱子宽度基于 category 自动计算（原 15）
      barCategoryGap: '100%' // 柱子间距（默认 20%，越大间距越大）
    });
    console.log(options.series)
  });

  return options;
}

// 2. 创建圆形要素
export const createCircle = (center, radiusKm: any) => {
  // 将经纬度转换为EPSG:3857坐标
  // 创建圆形几何（OpenLayers使用米作为单位）
  // 使用 Turf 生成缓冲区（地理坐标系）
  const point = turf.point(center);
  const buffered = turf.buffer(point, radiusKm, { units: 'kilometers' });

  // 将 GeoJSON 转换为 OpenLayers 几何对象
  const polygonGeometry = new GeoJSON().readGeometry(buffered.geometry, {
    dataProjection: 'EPSG:4326',
  });

  // 创建矢量要素并设置样式
  const feature = new Feature(polygonGeometry);
  feature.setStyle(new Style({
    fill: new Fill({
      color: 'rgba(255, 0, 0, 0.2)'
    }),
    stroke: new Stroke({
      color: '#ff0000',
      width: 2
    })
  }));

  return feature;
};

export function  createCircleByPolygon(polygon,radiusKm: any){
  const extent = polygon.getExtent(); // 获取外接矩形范围
  const center = getCenter(extent); // 外接矩形中心
  return createCircle(center,radiusKm);
}

export function drawBox(models: any) {
  const map = models.map;
  let draw = models.draw;
  // 停止上一次的绘制，没有此代码会出现重叠
  if (draw !== null) {
    map.removeInteraction(draw)
  }
  draw = createDraw(models.source,models.drawType, createBox);

  map.addInteraction(draw);
  return draw;
}

export function  createDraw(source,drawType,fun?){
  return new Draw({
    source: source,
    type: drawType,
    geometryFunction: fun()
  });
}
export function  createStyleDraw(source,drawType,fill,stroke){
  return  new Draw({
    source: source,
    type: drawType,
    style: createStyle(fill,stroke)
  });
}

export function stopDraw(models) {
  if (models.draw) {
    models.map.removeInteraction(models.draw)
    models.draw  = null;
  }
}

export function highlightFeatures(features) {
  features.forEach(feature => {
    feature.setStyle(createStyle('rgba(255,0,0,0.5)', 'darkgreen'));
  });
}

//'rgba(25, 205, 34, 0.5)',

export function findFeaturesInGeometry(geometry,targetSource) {
  const featuresInRange:any = [];

  targetSource.getFeatures().forEach((feature: any) => {
    if (feature.getGeometry().getType() === 'Point') {
       if(geometry.intersectsCoordinate(feature.getGeometry().getCoordinates())){
        featuresInRange.push(feature);
       }
    }
  });
  // 高亮或处理这些要素
  highlightFeatures(featuresInRange);
  return featuresInRange;
}
  
export function buildChartOption(seriesData){
  // 提取关键数据

const categories = seriesData.category;
const values = seriesData.data.map(Number);
const coordinates = seriesData.coordinates.map(Number);

// 生成 ECharts 配置
const option = {
  tooltip: {
    trigger: 'item',
    formatter: params => `${params.seriesName}<br/>${params.name}: ${params.value}`
  },
  xAxis: { show: false }, // 隐藏默认坐标轴
  yAxis: { show: false },
  series: categories.map((category, index) => ({
    name: category,
    type: 'bar',
    data: [{
      name: seriesData.name,
      value: values[index],
      // 将经纬度转换为屏幕坐标
      coord: coordinates
    }],
    barWidth: seriesData.barWidth,
    itemStyle: {
      color: ['#5470c6', '#91cc75', '#fac858', '#ee6666', '#73c0de', '#3ba272', '#fc8452'][index]
    },
    stack: '总量', // 堆叠显示（可选）
    label: {
      show: true,
      position: 'top',
      formatter: '{c}'
    }
  }))
};

// 渲染图表
return option;
}

export function speedStyle(startTime,speed,fill,color) {
  const elapsed = Date.now() - startTime;
  //const speed = 0.1; // 控制旋转速度
  return new Style({
    fill: new Fill({
      color: fill
    }),
      stroke: new Stroke({
          color: color, // 半透明蓝色
          width: 1,
          lineDash: [20, 20], // 虚线模式：20像素实线，20像素间隔
          lineDashOffset: -elapsed * speed // 动态偏移量
      })
  });
}


export function addBlinkingPoint(points,color,models) {
  let opacity = 1;
  let direction = -0.05; // 透明度变化步长
  let animationId:any = null;
  models.isAnimating = true; 
  const animate = () => {
    if(!models.isAnimating ){
      return;
    }
    opacity += direction;
    if (opacity <= 0 || opacity >= 1) direction *= -1;

    points.forEach(point =>{
      point.setStyle(new Style({
        image: new Circle({
          radius: 10,
          fill: new Fill({
            color: `rgba(${color}, ${opacity})`
          })
        })
      }));
    })

    animationId = requestAnimationFrame(animate);
  };

  animate();
  return animationId;
}


export function  fireStyle() {
  return new Style({
  image: new Circle({
    radius: 7,
    fill: new Fill({
      color: 'rgba(255, 0, 0, 0.5)'
    }),
    stroke: new Stroke({
      color: 'red',
      width: 2
    })
  })
});
}


export function  getDynamicStyle(radius: number): Style {
  return new Style({
    image: new Circle({
      radius: Math.min(7 + radius / 50, 30),
      fill: new Fill({
        color: `rgba(255, ${Math.max(0, 150 - radius)}, 0, 0.7)`
      }),
      stroke: new Stroke({
        color: 'darkred',
        width: 2
      })
    })
  });
}